package com.xinggq.pay.service.pay.channel.yse.other.refund;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson2.JSONObject;
import com.xinggq.common.utils.TradeNoGenerator;
import com.xinggq.pay.api.dto.YseCommonRefundReqDTO;
import com.xinggq.pay.api.dto.YseCommonRefundRespDTO;
import com.xinggq.pay.api.exception.PayException;
import com.xinggq.pay.service.context.AppIdContext;
import com.xinggq.pay.service.pay.channel.yse.other.refund.dto.YseRefundParamDTO;
import com.xinggq.pay.service.entity.PayOrderEntity;
import com.xinggq.pay.service.entity.YsePayConfigEntity;
import com.xinggq.pay.service.adaptor.YseApiAdaptor;
import com.xinggq.pay.service.enums.PayChannelEnum;
import com.xinggq.pay.service.enums.TradeTypeEnum;
import com.xinggq.pay.service.pay.channel.yse.enums.YseMethodEnum;
import com.xinggq.pay.service.pay.channel.yse.other.refund.dto.YseRefundReqDTO;
import com.xinggq.pay.service.pay.channel.yse.other.refund.dto.YseRefundRespDTO;
import com.xinggq.pay.service.pay.channel.yse.utils.YseOutTradeNoUtil;
import com.xinggq.pay.service.pay.channel.yse.utils.YseUtil;
import com.xinggq.pay.service.service.PayOrderService;
import com.xinggq.pay.service.service.YsePayConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


/**
 * 银盛退款服务
 * @Description
 * @Author xinggq
 * @Date 2025/9/12
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class YseRefundServiceImpl {


  private final YseApiAdaptor yseApiAdaptor;
  private final PayOrderService payOrderService;
  private final YsePayConfigService ysePayConfigService;

  public YseCommonRefundRespDTO refund(YseCommonRefundReqDTO refundReqDTO) {
    Validator.validateNotNull(refundReqDTO, "银盛接口参数不能为空");
    //先查询支付单
    PayOrderEntity payOrder = payOrderService.findByMerchantOrderNo(refundReqDTO.getPayMerchantOutTradeNo());
    Validator.validateNotNull(payOrder, "未查询到对应支付订单");

    YseRefundParamDTO refundParam = new YseRefundParamDTO();
    refundParam.setRefundAmount(refundReqDTO.getRefundAmount());
    refundParam.setRefundReason(refundReqDTO.getRefundReason());
    refundParam.setPayTradeNo(payOrder.getChannelTradeNo());
    refundParam.setChannelTradeNo(YseOutTradeNoUtil.createTradeNo());
    refundParam.setPayWay(payOrder.getPayWay());
    String refundTradeNo = TradeNoGenerator.getInstance().nextTradeNo();
    refundParam.setTradeNo(refundTradeNo);
    refundParam.setMerchantOutTradeNo(refundReqDTO.getMerchantOutTradeNo());
    refundParam.setPayMerchantOutTradeNo(refundReqDTO.getPayMerchantOutTradeNo());

    YseRefundRespDTO refundResult = refund(refundParam);
    if (refundResult.isSuccess()) {
      return YseCommonRefundRespDTO.builder()
          .tradeNo(refundTradeNo)
          .merchantOutTradeNo(refundReqDTO.getMerchantOutTradeNo())
          .paymerchantOutTradeNo(refundReqDTO.getMerchantOutTradeNo())
          .build();
    }
    throw new PayException(String.format("退款失败,失败原因：{%s}", refundResult.getErrorMsg()));
  }

  /**
   * 保存退款单记录
   */
  private void saveRefundOrder(YseRefundParamDTO refundParam) {
    PayOrderEntity refundOrder = new PayOrderEntity();
    refundOrder.setAppId(AppIdContext.getAppId());
    refundOrder.setTradeNo(refundParam.getTradeNo());
    refundOrder.setMerchantOrderNo(refundParam.getMerchantOutTradeNo());
    refundOrder.setChannelTradeNo(refundParam.getChannelTradeNo());
    refundOrder.setChannelType(PayChannelEnum.YSE.getCode());
    refundOrder.setPayWay(refundParam.getPayWay());
    refundOrder.setTradeType(TradeTypeEnum.REFUND.getCode());
    refundOrder.setAmount(refundParam.getRefundAmount());
    refundOrder.setSubject(
        "退款-" + (refundParam.getRefundReason() != null ? refundParam.getRefundReason()
            : "银盛退款"));
    // 设置原支付订单号，用于关联原支付订单
    refundOrder.setOriginalMerchantOrderNo(refundParam.getPayMerchantOutTradeNo());
    // 退款未完成
    refundOrder.setPayState(0);
    payOrderService.save(refundOrder);
    log.info("保存退款单记录成功，退款单号：{}", refundParam);
  }

  private YseRefundRespDTO refund(YseRefundParamDTO payParamDto) {
    Validator.validateNotNull(payParamDto, "银盛接口参数不能为空");
    // 获取数据库中的银盛当前支付渠道配置
    YsePayConfigEntity ysePayConfig = ysePayConfigService.getConfigByMethod(
        YseMethodEnum.REFUND_SPLIT);
    Validator.validateNotNull(ysePayConfig,
        String.format("银盛接口配置为空，接口方法:{%s}", YseMethodEnum.REFUND_SPLIT.getMethod()));
    // 保存退款单
    saveRefundOrder(payParamDto);
    // 创建银盛参数
    String requestData = buildRefundPayDto(payParamDto, ysePayConfig);
    String respStr = yseApiAdaptor.post(payParamDto.getChannelTradeNo(), requestData,
        YseMethodEnum.REFUND_SPLIT.getGatewayUrl());
    return JSONObject.parseObject(respStr, YseRefundRespDTO.class);
  }

  private String buildRefundPayDto(YseRefundParamDTO payParamDto, YsePayConfigEntity ysePayConfig) {
    YseRefundReqDTO yseRefund = YseRefundReqDTO.buildYseRefundReqDTO(payParamDto, ysePayConfig);
    return YseUtil.mapToSortedString(BeanUtil.beanToMap(yseRefund, true, true));
  }
}
